package BasicEngine
{
	import flash.display.SimpleButton;
	import flash.utils.Dictionary;

	//调度器
	public class Dispatcher
	{
		public static var Clock:ClockUnit;  
		public static var TimeTaskHead:TaskUnit;
		public static var FrameTaskHead:TaskUnit;				
		private static var nextId:Number;
		private static var invokeTime1:int;
		private static var invokeBusy1:Boolean;
		private static var invokeTime2:int;
		private static var invokeBusy2:Boolean;
		
		public function Dispatcher()
		{			
		}
		
		//初始化
		public static function Init():void
		{
			Clock = new ClockUnit();
			TimeTaskHead = null;
			FrameTaskHead = null;
		}
		
		//调度器循环
		public static function ExecuteUpdate():void
		{
			Clock.Update();			
			ExecuteTimeTask();
			ExecuteFrameTask();
		}
		
		//注册任务                     //任务类型，0：时间任务 1:帧任务
		public static function RegistTaskUnit(_type:int,_start:Number,_interval:Number,_duration:Number,_data:Object,_proc:Function):Number
		{
			if(_duration != 0)
				_duration = _start + _duration -1;
			nextId ++;
			var unit:TaskUnit = new TaskUnit();
			unit.taskDuration = _duration;
			unit.taskStart = _start;
			unit.taskInterval = _interval;
			unit.taskNext = _start;
			unit.ID = nextId;
			unit.Proc = _proc;
			unit.ProcData= _data;
			if(_type == 0)
				InsertTimeTask(unit);
			else
				InsertFrameTask(unit);
			return unit.ID;
		}
		
		//执行时间任务
		private static function ExecuteTimeTask():void
		{
			var head:TaskUnit = GetTimeTaskHead();
			while (head != null)
			{
				head.Proc(head.ProcData);
				
				head.taskLast = head.taskNext;
				head.taskNext += head.taskInterval;
				if(head.taskDuration == 0 || head.taskDuration >= head.taskNext)
				{
					InsertTimeTask(head);
				}
				else
				{
					head = null;
				}
				head = GetTimeTaskHead();				
			}
		}		
		
		//把一个时间任务插入到任务队列里面
		public static function InsertTimeTask(_pTask:TaskUnit):void
		{
			if(TimeTaskHead == null)  //队列为空，则此任务为头任务
			{
				_pTask.PNext = null;
				TimeTaskHead = _pTask;
			}
			else if(_pTask.taskNext <= TimeTaskHead.taskNext)//如果给定任务时间小于头任务时间，则此任务为头任务
			{
				_pTask.PNext = TimeTaskHead;
				TimeTaskHead = _pTask;
			}
			else
			{
				var unit:TaskUnit = TimeTaskHead;
				while(unit != null)
				{
					if(unit.PNext == null)//说明到了任务尾,把此任务放在最后面
					{
						_pTask.PNext = null;
						unit.PNext = _pTask;
						break;
					}
					else if(unit.PNext.taskNext > _pTask.taskNext)//下一任务的时间晚于此任务，则把此任务插在前面
					{
						_pTask.PNext = unit.PNext;
						unit.PNext = _pTask;
						break;
					}
					unit = unit.PNext;
				}
			}
		}		
		
		//取得时间任务的头任务
		private static function GetTimeTaskHead():TaskUnit
		{
			var head:TaskUnit = null;
			if ((TimeTaskHead != null) && (TimeTaskHead.taskNext <= Clock.SystemTime))
			{
				head = TimeTaskHead;
				TimeTaskHead = head.PNext;
				head.PNext = null;
			}
			return head;
		}
		
		//执行帧任务
		private static function ExecuteFrameTask():void
		{
			var head:TaskUnit = GetFrameTaskHead();
			while (head != null)
			{
				head.Proc(head.ProcData);
				
				head.taskLast = head.taskNext;
				head.taskNext += head.taskInterval;
				if(head.taskDuration == 0 || head.taskDuration >= head.taskNext)
				{
					InsertFrameTask(head);
				}
				else
				{
					head = null;
				}
				head = GetFrameTaskHead();				
			}
		}
		
		//把一个帧任务插入到任务队列里面
		public static function InsertFrameTask(_pTask:TaskUnit):void
		{
			if(FrameTaskHead == null)  //队列为空，则此任务为头任务
			{
				_pTask.PNext = null;
				FrameTaskHead = _pTask;
			}
			else if(_pTask.taskNext <= FrameTaskHead.taskNext)//如果给定任务时间小于头任务时间，则此任务为头任务
			{
				_pTask.PNext = FrameTaskHead;
				FrameTaskHead = _pTask;
			}
			else
			{
				var unit:TaskUnit = FrameTaskHead;
				while(unit != null)
				{
					if(unit.PNext == null)//说明到了任务尾,把此任务放在最后面
					{
						_pTask.PNext = null;
						unit.PNext = _pTask;
						break;
					}
					else if(unit.PNext.taskNext > _pTask.taskNext)//下一任务的时间晚于此任务，则把此任务插在前面
					{
						_pTask.PNext = unit.PNext;
						unit.PNext = _pTask;
						break;
					}
					unit = unit.PNext;
				}
			}
		}
		
		//(1)等待是否完成 （2）执行函数 （3）每次等待时间 （4）执行函数所需数据 （5）最大等待时间
		public static function BeginInvoke(_getFlag:Function,_callBack:Function, _callTime:int,_data:Object,_invokeMax:int = 10000):void
		{
			if (invokeBusy1)
			{
				if ( Clock.SystemTime  > invokeTime1)
				{
					invokeBusy1 = false;
					invokeTime1 = 0;
					trace("超时,抛弃任务");
					return;
				}				
			}
			else
			{
				invokeBusy1 = true;				
				invokeTime1 = Clock.SystemTime + _invokeMax;
			}
			var flag:Boolean = _getFlag();
			if (flag)
			{				
				_callBack(_data);
			}
			else  
			{
			     RegistTaskUnit(0, Clock.SystemTime + _callTime, 1,1, _data, function(_data:Object):void
			     {
			     	BeginInvoke(_getFlag,  _callBack, _callTime, _data);
			     });
			}
		}
				
		//取得帧任务的头任务
		private static function GetFrameTaskHead():TaskUnit
		{
			var head:TaskUnit = null;
			if ((FrameTaskHead != null) && (FrameTaskHead.taskNext <= Clock.FrameCount))
			{
				head = FrameTaskHead;
				FrameTaskHead = head.PNext;
				head.PNext = null;
			}
			return head;
		}		
	}
}